#pragma once
#include "../Base.h"
//0x30 bytes (sizeof)



typedef
VOID
(*PKNORMAL_ROUTINE) (
    IN PVOID NormalContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    );

typedef
VOID
(*PKKERNEL_ROUTINE) (
    IN struct _KAPC* Apc,
    IN OUT PKNORMAL_ROUTINE* NormalRoutine,
    IN OUT PVOID* NormalContext,
    IN OUT PVOID* SystemArgument1,
    IN OUT PVOID* SystemArgument2
    );
typedef
VOID
(*PKRUNDOWN_ROUTINE) (
    IN struct _KAPC* Apc
    );

typedef enum _KAPC_ENVIRONMENT {
    OriginalApcEnvironment,
    AttachedApcEnvironment,
    CurrentApcEnvironment,
    InsertApcEnvironment
} KAPC_ENVIRONMENT;

EXTERN_C
VOID
KeInitializeApc(
    __out PRKAPC Apc,
    __in PRKTHREAD Thread,
    __in KAPC_ENVIRONMENT Environment,
    __in PKKERNEL_ROUTINE KernelRoutine,
    __in_opt PKRUNDOWN_ROUTINE RundownRoutine,
    __in_opt PKNORMAL_ROUTINE NormalRoutine,
    __in_opt KPROCESSOR_MODE ApcMode,
    __in_opt PVOID NormalContext
);

EXTERN_C
BOOLEAN
KeInsertQueueApc(
    __inout PRKAPC Apc,
    __in_opt PVOID SystemArgument1,
    __in_opt PVOID SystemArgument2,
    __in KPRIORITY Increment
);

typedef struct _APC_ENTRY {
    KAPC apc;
    KEVENT finishEvent;
    PKNORMAL_ROUTINE func;
}APC_ENTRY,*PAPC_ENTRY;

typedef
BOOLEAN
(*pfnKeAlertThread)(
    __inout PKTHREAD Thread,
    __in KPROCESSOR_MODE AlertMode
    );

EXTERN_C PAPC_ENTRY apc_entry;
EXTERN_C
BOOLEAN InsertApc(ULONG tid, PKNORMAL_ROUTINE func);



EXTERN_C void APC_TEST();